package edu.cuit.zhuyimeng.ticket.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.dynamic.datasource.annotation.Master;
import edu.cuit.zhuyimeng.flight.api.controller.FlightManagerApiController;
import edu.cuit.zhuyimeng.flight.api.dto.FlightInfoDTO;
import edu.cuit.zhuyimeng.framework.cache.aspect.annotation.CacheInvalidatePattern;
import edu.cuit.zhuyimeng.framework.common.exception.UpdateException;
import edu.cuit.zhuyimeng.framework.common.system.enums.FlightStatus;
import edu.cuit.zhuyimeng.framework.common.system.enums.SysConstants;
import edu.cuit.zhuyimeng.framework.workflow.util.ProcessUtils;
import edu.cuit.zhuyimeng.ticket.controller.vo.TicketInfoVO;
import edu.cuit.zhuyimeng.ticket.enums.CacheConstants;
import edu.cuit.zhuyimeng.ticket.exception.BuyTicketException;
import edu.cuit.zhuyimeng.ticket.exception.RefundTicketException;
import edu.cuit.zhuyimeng.ticket.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 订票调度实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class TicketDispatchService implements ITicketDispatchService {

    private final IUserTicketManager userTicketManager;
    private final ITicketSessionManager ticketSessionManager;
    private final IDispatchJobService dispatchJobService;

    private final RuntimeService runtimeService;
    private final TaskService taskService;

    private final FlightManagerApiController flightManagerApiController;

    @Autowired
    @Lazy
    private IFlightService flightService;


    @Override
    public void buyTicket(Long flightId) {
        String loginId = (String) StpUtil.getLoginId();
        if (userTicketManager.getUserTicketInfo(loginId) != null) {
            throw new BuyTicketException("你已经买了票了");
        }
        FlightInfoDTO flightInfo = flightService.queryFlightInfo(flightId);
        if (flightInfo == null) {
            throw new BuyTicketException("当前航班不存在");
        }
        if (!ticketSessionManager.buyTicket(flightInfo)) {
            throw new BuyTicketException("当前航班不能买票");
        }
        userTicketManager.addUserTicket(loginId,flightId);
    }

    @Override
    public void refundTicket(Long flightID) {
        String loginId = (String) StpUtil.getLoginId();
        TicketInfoVO userTicketInfo = userTicketManager.getUserTicketInfo(loginId);
        if (userTicketInfo == null) {
            throw new RefundTicketException("你还没有买票");
        }
        if (userTicketInfo.getFlightInfo().getId().intValue() != flightID) {
            throw new RefundTicketException("您买的不是当前航班的票");
        }
        if (userTicketInfo.getFlightInfo().getStatus().intValue() != FlightStatus.BOOKING.getType().intValue()) {
            throw new RefundTicketException("航班订票阶段已结束，不能退票了");
        }
        FlightInfoDTO flightInfo = flightService.queryFlightInfo(flightID);
        if (flightInfo == null) {
            throw new RefundTicketException("当前航班不存在");
        }
        if (!ticketSessionManager.refundTicket(flightInfo)) {
            throw new RefundTicketException("当前航班不能退票");
        }
        userTicketManager.removeUserTicket(loginId);
    }

    @Override
    @CacheInvalidatePattern(name = CacheConstants.TICKET_INFO,pattern = "*")
    public void openTicketDispatch(Long flightId) {
        FlightInfoDTO flightInfo = flightService.queryFlightInfo(flightId);
        ticketSessionManager.openTicketDispatch(flightInfo);
        dispatchJobService.setCloseBookingJob(flightId);
        log.info("ID为：{} 的航班已开放订票",flightId);
    }

    @Override
    @CacheInvalidatePattern(name = CacheConstants.TICKET_INFO,pattern = "*")
    public void closeTicketDispatch(Long flightID) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(String.valueOf(flightID)).includeProcessVariables().singleResult();
        if (processInstance.getProcessVariables().get(SysConstants.STATUS) != FlightStatus.BOOKING.getType()) {
            throw new UpdateException("此航班不在订票阶段");
        }
        ticketSessionManager.closeTicketDispatch(flightID);
        Task task = taskService.createTaskQuery().processInstanceBusinessKey(String.valueOf(flightID)).singleResult();
        taskService.complete(task.getId());

        Map<String, Object> processVariables = processInstance.getProcessVariables();
        processVariables.put(SysConstants.STATUS,FlightStatus.WAITING_TAKEOFF.getType());
        processVariables.remove(SysConstants.JOB_ID_KEY);
        ProcessUtils.setVariables(processInstance,processVariables);

        dispatchJobService.inactivateCloseBookingJob(flightID);
        flightManagerApiController.refreshFlightCache(flightID);
        log.info("ID为：{} 的航班已关闭订票",flightID);
    }
}
